From: Étienne Mollier Date: Wed, 3 Jun 2026 17:20:09 +0000 (+0200) Subject: CVE-2026-5663.patch: new: fix CVE-2026-5663. X-Git-Tag: archive/raspbian/3.7.0+really3.7.0-5+rpi1^2~17 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=449d8d60f851bf804b3d4361c62389270ac2844f;p=dcmtk.git CVE-2026-5663.patch: new: fix CVE-2026-5663. This change introduces guardrails to prevent risks of shell code injection. Closes: #1133001 --- diff --git a/debian/patches/CVE-2026-5663.patch b/debian/patches/CVE-2026-5663.patch new file mode 100644 index 00000000..1769102a --- /dev/null +++ b/debian/patches/CVE-2026-5663.patch @@ -0,0 +1,232 @@ +Applied-Upstream: edbb085e45788dccaf0e64d71534cfca925784b8 +Author: Marco Eichelberg +Last-Update: 2026-03-21 +Description: Sanitize all strings passed to the exec options. + Sanitize the text fields from incoming DICOM associations and DICOM objects + (such as Study Instance UID, SOP Instance UID, Patient's Name) and the + calling SCU's network presentation address by removing special characters + that may be interpreted as shell escape characters when one of the + execution options (e.g. --exec-on-reception) is in use. + . + Thanks to Machine Spirits UG (haftungsbeschränkt) for the bug report, + detailed analysis and proof of concept. + . + This closes DCMTK issue #1194. +Bug: https://support.dcmtk.org/redmine/issues/1194 +Bug-Debian: https://bugs.debian.org/1133001 +Reviewed-By: Étienne Mollier + +--- dcmtk.orig/dcmnet/apps/storescp.cc ++++ dcmtk/dcmnet/apps/storescp.cc +@@ -1,6 +1,6 @@ + /* + * +- * Copyright (C) 1994-2025, OFFIS e.V. ++ * Copyright (C) 1994-2026, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by +@@ -1601,7 +1601,9 @@ + calledAETitle.clear(); + } + // store calling presentation address (i.e. remote hostname) +- callingPresentationAddress = OFSTRING_GUARD(assoc->params->DULparams.callingPresentationAddress); ++ callingPresentationAddress = "\""; ++ callingPresentationAddress += OFSTRING_GUARD(assoc->params->DULparams.callingPresentationAddress); ++ callingPresentationAddress += "\""; + + /* now do the real work, i.e. receive DIMSE commands over the network connection */ + /* which was established and handle these commands correspondingly. In case of */ +@@ -1965,6 +1967,7 @@ + dateTime.getTime().getHour(), dateTime.getTime().getMinute(), dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond()); + + OFString subdirectoryName; ++ OFString s; + switch (opt_sortStudyMode) + { + case ESM_Timestamp: +@@ -1979,15 +1982,27 @@ + subdirectoryName = opt_sortStudyDirPrefix; + if (!subdirectoryName.empty()) + subdirectoryName += '_'; +- subdirectoryName += currentStudyInstanceUID; +- OFStandard::sanitizeFilename(subdirectoryName); ++ s = currentStudyInstanceUID; ++ OFStandard::sanitizeFilename(s); ++ if (s != currentStudyInstanceUID) ++ { ++ OFLOG_WARN(storescpLogger, "Sanitized unusual characters in Study Instance UID, converted from \"" << currentStudyInstanceUID << "\" to \"" << s << "\"."); ++ } ++ subdirectoryName += s; + break; + case ESM_PatientName: + // pattern: "[Patient's Name]_[YYYYMMDD]_[HHMMSSMMM]" + subdirectoryName = currentPatientName; ++ OFStandard::sanitizeFilename(subdirectoryName); ++ if (subdirectoryName != currentPatientName) ++ { ++ // It is quite normal that we need to sanitize characters in PatientName. ++ // Therefore, this is only a debug message and not a warning, unlike the other ++ // messages about sanitized fields, which are normally not expected. ++ OFLOG_DEBUG(storescpLogger, "Sanitized characters in Patient Name, converted from \"" << currentPatientName << "\" to \"" << subdirectoryName << "\"."); ++ } + subdirectoryName += '_'; + subdirectoryName += timestamp; +- OFStandard::sanitizeFilename(subdirectoryName); + break; + case ESM_None: + break; +@@ -2196,8 +2211,13 @@ + else + { + // Use the SOP instance UID as found in the C-STORE request message as part of the filename +- OFString uid(OFSTRING_GUARD(req->AffectedSOPInstanceUID)); ++ OFString s(OFSTRING_GUARD(req->AffectedSOPInstanceUID)); ++ OFString uid = s; + OFStandard::sanitizeFilename(uid); ++ if (uid != s) ++ { ++ OFLOG_WARN(storescpLogger, "Sanitized unusual characters in SOP Instance UID, converted from \"" << s << "\" to \"" << uid << "\"."); ++ } + OFStandard::snprintf(imageFileName, sizeof(imageFileName), "%s%c%s.%s%s", opt_outputDirectory.c_str(), PATH_SEPARATOR, dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), + uid.c_str(), opt_fileNameExtension.c_str()); + } +@@ -2367,16 +2387,19 @@ + if( !opt_ignore ) + { + // perform substitution for placeholder #p (depending on presence of any --sort-xxx option) ++ // Note: We do not enclose this in quotes because it may be used as part of a path expression. + OFString dir = (opt_sortStudyMode == ESM_None) ? opt_outputDirectory : subdirectoryPathAndName; + cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), dir ); + + // perform substitution for placeholder #f; note that outputFileNameArray.back() + // always contains the name of the file (without path) which was written last. ++ // Note: We do not enclose this in quotes because it may be used as part of a path expression. + OFString outputFileName = outputFileNameArray.back(); + cmd = replaceChars( cmd, OFString(FILENAME_PLACEHOLDER), outputFileName ); + } + +- // perform substitution for placeholder #a ++ // perform substitution for placeholder #a. ++ // Note that this string is already enclosed in double quotes at this point + s = callingAETitle; + sanitizeAETitle(s); + if (s != callingAETitle) +@@ -2385,7 +2408,8 @@ + } + cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), s ); + +- // perform substitution for placeholder #c ++ // perform substitution for placeholder #c. ++ // Note that this string is already enclosed in double quotes at this point + s = calledAETitle; + sanitizeAETitle(s); + if (s != calledAETitle) +@@ -2394,8 +2418,15 @@ + } + cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), s ); + +- // perform substitution for placeholder #r +- cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), callingPresentationAddress ); ++ // perform substitution for placeholder #r. ++ // Note that this string is already enclosed in double quotes at this point ++ s = callingPresentationAddress; ++ sanitizeAETitle(s); ++ if (s != callingPresentationAddress) ++ { ++ OFLOG_WARN(storescpLogger, "Sanitized unusual characters in calling presentation address, converted from " << callingPresentationAddress << " to " << s << "."); ++ } ++ cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), s ); + + // Execute command in a new process + executeCommand( cmd ); +@@ -2500,20 +2531,38 @@ + OFString s; + + // perform substitution for placeholder #p; #p will be substituted by lastStudySubdirectoryPathAndName ++ // Note: We do not enclose this in quotes because it may be used as part of a path expression. + cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), lastStudySubdirectoryPathAndName ); + +- // perform substitution for placeholder #a ++ // perform substitution for placeholder #a. ++ // Note that this string is already enclosed in double quotes at this point + s = callingAETitle; + sanitizeAETitle(s); ++ if (s != callingAETitle) ++ { ++ OFLOG_WARN(storescpLogger, "Sanitized unusual characters in calling aetitle, converted from " << callingAETitle << " to " << s << "."); ++ } + cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), s ); + +- // perform substitution for placeholder #c ++ // perform substitution for placeholder #c. ++ // Note that this string is already enclosed in double quotes at this point + s = calledAETitle; + sanitizeAETitle(s); ++ if (s != calledAETitle) ++ { ++ OFLOG_WARN(storescpLogger, "Sanitized unusual characters in called aetitle, converted from " << calledAETitle << " to " << s << "."); ++ } + cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), s ); + +- // perform substitution for placeholder #r +- cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), callingPresentationAddress ); ++ // perform substitution for placeholder #r. ++ // Note that this string is already enclosed in double quotes at this point ++ s = callingPresentationAddress; ++ sanitizeAETitle(s); ++ if (s != callingPresentationAddress) ++ { ++ OFLOG_WARN(storescpLogger, "Sanitized unusual characters in calling presentation address, converted from " << callingPresentationAddress << " to " << s << "."); ++ } ++ cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), s ); + + // Execute command in a new process + executeCommand( cmd ); +--- dcmtk.orig/ofstd/libsrc/ofstd.cc ++++ dcmtk/ofstd/libsrc/ofstd.cc +@@ -3402,16 +3402,26 @@ + } + + ++static const char sanitized_filename_charset[] = ++{ ++ ' ', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '-', '.', '_', ++ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '_', '_', '_', '_', '_', ++ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', ++ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '_', '_', '_', '_', ++ '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', ++ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '_', '_', '_', '_', '_' ++}; ++ ++ + void OFStandard::sanitizeFilename(OFString& fname) + { + const size_t len = fname.length(); ++ char c; + for (size_t i = 0; i < len; ++i) + { +-#ifdef _WIN32 +- if ((fname[i] == PATH_SEPARATOR) || (fname[i] == '/')) fname[i] = '_'; +-#else +- if (fname[i] == PATH_SEPARATOR) fname[i] = '_'; +-#endif ++ c = fname[i]; ++ if (c != 0 && (c < 32 || c >= 127)) c = '_'; else c = sanitized_filename_charset[c-32]; ++ fname[i] = c; + } + } + +@@ -3423,11 +3433,7 @@ + char *c = fname; + while (*c) + { +-#ifdef _WIN32 +- if ((*c == PATH_SEPARATOR) || (*c == '/')) *c = '_'; +-#else +- if (*c == PATH_SEPARATOR) *c = '_'; +-#endif ++ if (*c < 32 || *c >= 127) *c = '_'; else *c = sanitized_filename_charset[*c-32]; + ++c; + } + } diff --git a/debian/patches/series b/debian/patches/series index cfe2d429..910203c1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -4,3 +4,4 @@ remove_version.patch skip-bigendian-roundtrip-failure.patch hurd.patch +CVE-2026-5663.patch